#include "stack.h"

#include <assert.h>
#include <stdlib.h>


typedef struct _stacknode{
	struct _stacknode *next;
	union{
		void *data;
		int idata;
	};

}StackNode;

struct _stack{
    StackNode *ptop;
    int length;
    void *(*stackMalloc)(size_t size);
    void (*stackFree)(void *ptr);
};

//栈游标
typedef struct _stackcursor{
	StackNode *pnode;
}StackCursor;

Stack *StackInit()
{
	Stack *pstack;
    pstack=(Stack*)malloc(sizeof(Stack));
    pstack->ptop=0;
    pstack->length=0;
    pstack->stackMalloc=malloc;
    pstack->stackFree=free;
    return pstack;
}

int StackPushInt(Stack *pstack,int data)
{
    assert(pstack);
    assert(data);
    StackNode *pnode;
    pnode=(StackNode*)(pstack->stackMalloc(sizeof(StackNode)));
    pnode->next=pstack->ptop;
    pnode->idata=data;
    pstack->ptop=pnode;
    pstack->length++;
    return data;
}

void *StackPush(Stack *pstack,void *data)
{
    assert(pstack);
    assert(data);
    StackNode *pnode;
    pnode=(StackNode*)(pstack->stackMalloc(sizeof(StackNode)));
    pnode->next=pstack->ptop;
    pnode->data=data;
    pstack->ptop=pnode;
    pstack->length++;
    return data;
}

int StackPopInt(Stack *pstack)
{
    assert(pstack);
    StackNode *pnode;
    if(pstack->length==0){
        return 0;
    }
    pnode=pstack->ptop;
    pstack->ptop=pstack->ptop->next;
    int data;
    data=pnode->idata;
    pstack->stackFree(pnode);
    pstack->length--;
    return data;
}

void *StackPop(Stack *pstack)
{
    assert(pstack);
    StackNode *pnode;
    if(pstack->length==0){
        return 0;
    }
    pnode=pstack->ptop;
    pstack->ptop=pstack->ptop->next;
    void *pdata;
    pdata=pnode->data;
    pstack->stackFree(pnode);
    pstack->length--;
    return pdata;
}

int StackLength(Stack *pstack)
{
    assert(pstack);
    return pstack->length;
}
Stack *StackEmpty(Stack *pstack)
{
	assert(pstack);
	while(pstack->length){
		StackPop(pstack);
	}
	pstack->length=0;
	pstack->ptop=0;
    return pstack;
}

StackCursor *StackGetCursor(Stack *pstack)
{
	assert(pstack);
	StackCursor *pcursor;
	pcursor=(StackCursor*)malloc(sizeof(StackCursor));
	pcursor->pnode=0;
	return pcursor;
}

void *StackForeach(Stack *pstack,StackCursor *pcursor)
{
	assert(pstack);
	assert(pcursor);
	if(pcursor->pnode==0){
		pcursor->pnode=pstack->ptop;
		if(pcursor->pnode){
					return pcursor->pnode->data;
				}else{
					return 0;
				}
	}else{
		pcursor->pnode=pcursor->pnode->next;
		if(pcursor->pnode){
			return pcursor->pnode->data;
		}else{
			return 0;
		}
	}
}

void StackAllocator(Stack *pstack,void *(*pmalloc)(size_t size),void (*pfree)(void *pdata))
{
	assert(pstack);
	pstack->stackMalloc=pmalloc;
	pstack->stackFree=pfree;
}

void *StackData(Stack *pstack)
{
	assert(pstack);
	if(pstack->length)
	return pstack->ptop->data;
	return 0;
}

int StackData(Stack *pstack)
{
	assert(pstack);
	if(pstack->length)
	return pstack->ptop->idata;
	return 0;
}


